package cz.muni.fi.pa165.library.backend;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.validation.constraints.NotNull;

/**
 * Reservation represents reservation of one book in library
 *
 * @author Marián Labuda
 * @version 1.2
 */
@Entity
public class Reservation implements Serializable {

    private static final long serialVersionUID = 1L;
    public static final int MAXIMUM_COUNT_OF_RESERVATIONS = 6;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long reservationID;
    @OneToOne
    @NotNull
    private Reader reader;
    @OneToOne
    @NotNull
    private Book book;
    @NotNull
    @Temporal(javax.persistence.TemporalType.TIMESTAMP)
    private Date reservationDate;

    public Reservation() {
    }

    /**
     * Create new Reservation. If any parameter is null then
     * IllegalArgumentException is thrown.
     *
     * @param readerID
     * @param bookID
     * @param reservationDate
     */
    public Reservation(Reader reader, Book book, Date reservationDate) {
        if (reader == null) {
            throw new IllegalArgumentException("Cannot create reservation for nobody");
        }
        if (book == null) {
            throw new IllegalArgumentException("Cannot create reservation of imaginary book");
        }
        if (reservationDate == null) {
            throw new IllegalArgumentException("Cannot create reservation outside the spacetime");
        }
        this.reader = reader;
        this.book = book;
        this.reservationDate = reservationDate;
    }

    public Long getReservationID() {
        return reservationID;
    }

    /**
     * This method can be used only for purpose of tests and similar cases. In
     * another case the ID is generaded automatically.
     *
     * If reservation ID is null or (lesser than or equals to 0), then
     * IllegalArgumentException is thrown.
     *
     * @param reservationID
     */
    public void setReservationID(Long reservationID) {
        if (reservationID == null) {
            throw new IllegalArgumentException("Cannot set null ID");
        }
        if (reservationID > 0) {
            this.reservationID = reservationID;
        } else {
            throw new IllegalArgumentException("Reservation ID must be greater than 0");
        }
    }

    public void setID(Long id) {
        reservationID = id;
    }

    public Reader getReader() {
        return reader;
    }

    public void setReader(Reader reader) {
        this.reader = reader;
    }

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }

    public Date getReservationDate() {
        return reservationDate;
    }

    public void setReservationDate(Date reservationDate) {
        this.reservationDate = reservationDate;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + (this.reader != null ? this.reader.hashCode() : 0);
        hash = 83 * hash + (this.book != null ? this.book.hashCode() : 0);
        hash = 83 * hash + (this.reservationDate != null ? this.reservationDate.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Reservation other = (Reservation) obj;
        if (this.reader == null || !this.reader.equals(other.reader)) {
            return false;
        }
        if (this.book == null || !this.book.equals(other.book)) {
            return false;
        }
        if (this.reservationDate == null || !this.reservationDate.equals(other.reservationDate)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Reservation{" + "reservationID=" + reservationID + ", reader=" + reader + ", book=" + book + ", reservationDate=" + reservationDate + '}';
    }
}
